#include <iostream>
#include <thread>
#include <cmath>

#include <ame.h>

using namespace std;

Mesh trinagle;
Object objTrinagle;
Transform transform;
threadControl coreCtrl;
Application application;
Window* window = nullptr;
OGLRender* render = nullptr;
Shader* shader = nullptr;
unsigned int fps = 0;
bool run = true;

void doSomething(){
    transform.setX(23);
    transform.setY(12);
    transform.setZ(112);

    cout << transform.returnX() << endl;
    cout << transform.returnY() << endl;
    cout << transform.returnZ() << endl;
}

void calcFPS () {
    while ( run ) {
        application.time.wait (1000);
        cout << "FPS:\t" << fps << endl;
        fps = 0;
    }
}

void Update () {
    double rotation = 0.01;
    
    objTrinagle.transform.rotate ( ame::vec3( 0, 0, rotation ) );
    objTrinagle.transform.setPosition ( ame::vec3 ( application.input.mouse.posX/10, 
                                                    application.input.mouse.posY/10, 0.0 ) );
    objTrinagle.transform.updateMesh ();
    
    shader -> Bind ();
    shader -> SetUniform ( "scale", sin ( application.input.mouse.posY /10 ) );
    shader -> SetUniform ( "uColor", ame::vec4 ( 1.0, 1.0, 1.0, 1.0 ) );
    
    render -> Draw( trinagle );
    
    if ( application.input.keyboard.key == 'L' ) {
        trinagle.type = Line;
    } else if ( application.input.keyboard.key == 'P' ){
        trinagle.type = Polygon;
    } else if ( application.input.keyboard.key == 'T' ) {
        trinagle.type = Point;
    }
    
    fps++;
}

int main ()
{
    application.appName = "AMEP";
    application.companyName = "assblast";
    application.update = Update;
    application.openGLTools.OpenGLContext = OGLC_GLFW;
    
    application.settings.windowName = "AREP";
    application.settings.windowWidth = 960;
    application.settings.windowHeight = 540;
    application.settings.windowMonitor = 0;
    application.settings.windowResizeble = false;
    application.settings.MSAA = 8;
    
    window = new Window ( &application );
    render = new OGLRender ( &application, window );
    shader = new Shader ( "./res/basicShader" );

    trinagle.points.resize ( 6 );
    trinagle.viewPoints.resize ( 6 );
    trinagle.textureCoordinate.resize ( 6 );
    trinagle.pointSize.resize ( 3 );
    trinagle.polygonMaterial.resize ( 1 );
    trinagle.polygonColor.resize ( 3 );
    trinagle.type = Line;
    trinagle.measurement = 3; //3D
    trinagle.polygonMaterial [0] = MATERIAL_COLOR;

    for ( unsigned int i = 0; i < trinagle.pointSize.size (); i++ ) {
        trinagle.pointSize [i] = 0.1;
    }
    
    trinagle.points = {
        ame::vec3 ( 0.0, 0.5, 0.0 ),
        ame::vec3 ( 0.5, -0.5, 0.0 ),
        ame::vec3 ( -0.5, -0.5, 0.0 ),
    };
    trinagle.textureCoordinate = {
        ame::vec2 ( 0.0, 0.0 ),
        ame::vec2 ( 0.5, 1.0 ),
        ame::vec2 ( 1.0, 0.0 ),
    };

    trinagle.viewPoints = trinagle.points;
    trinagle.centerPoint.x = 0;
    trinagle.centerPoint.y = 0;
    trinagle.centerPoint.z = 0;
    
    trinagle.computeCollisionRadius ();
    trinagle.polygonColor[0] = ame::vec4 ( 0.4, 0.6, 0.8, 1.0 ); //RGBA
    trinagle.polygonColor[1] = ame::vec4 ( 0.6, 0.4, 0.8, 1.0 );
    trinagle.polygonColor[2] = ame::vec4 ( 0.4, 0.8, 0.4, 1.0 );
    
    objTrinagle.transform.setMesh( &trinagle );
    objTrinagle.transform.setPosition( ame::vec3( 0.0, 0.0, 0.0 ) );
    objTrinagle.transform.setRotation( ame::vec3( 0.0, 0.0, 0.0 ) );

    coreCtrl.threads.resize ( 1 );
    coreCtrl.threads [0] = new std::thread ( doSomething );
    coreCtrl.threads [1] = new std::thread ( calcFPS );
    
    render -> joinToMainCycle ();

    run = false;
    coreCtrl.threads [0] -> detach ();
    coreCtrl.threads [1] -> detach ();

    return 0;
}
